#pragma once
#include "Connection.hpp"
#include "Socket.hpp"
#include "Common.hpp"
#include <functional>

using func_t = std::function<std::string(std::string &)>;
class ioservice : public Connection
{
public:
    ioservice(int sockfd)
    {
        SetSockfd(sockfd);
        SetEvents(EPOLLIN | EPOLLET);
        SetNonBlock(_sockfd); // 设置自己的文件描述符为非阻塞
    }

    void RegisterFunc(func_t func)
    {
        _func = func;
    }

    virtual void Recver() override
    {
        while (true)
        {
            char buffer[1024];
            int n = ::recv(_sockfd, buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                /*读取成功*/
                buffer[n] = 0;
                std::string message = std::string(buffer);
                InTOinbuffer(message);
            }
            else if (n == 0)
            {
                Excepter();
                return;
            }
            else
            {
                if (errno == EAGAIN | errno == EWOULDBLOCK)
                {
                    LOG(LogLevel::INFO) << "底层数据读取完毕";
                    break;
                }
                if (errno == EINTR)
                {
                    LOG(LogLevel::INFO) << "信号中断";
                    return;
                }
                else
                {
                    Excepter();
                    break;
                }
            }
        }
        /*这里处理读取到inbuffer中的报文，利用协议来判断是否是完整的报文*/
        std::string request;
        request = _func(Getinbuffer());
        if (!request.empty())
        {
            InTooutbuffer(request);
            Sender(); // 完整报文存放在request中直接进行Sender()
        }
    }

    virtual void Sender() override
    {
        /*在收到完整报文后，对报文处理得到应答，直接先将应答进行发送，如果发送失败进行写关心，写关心按需设置*/
        while (!IsOutBufferEmpty())
        {
            int n = ::send(_sockfd, _outbuffer.c_str(), _outbuffer.size() - 1, 0); // 直接将应答全部发送
            if (n > 0)
            {
                std::cout << "<Getoutbuffer: " << Getoutbuffer() << std::endl;
                DisCardOutString(n); // 将发出去的应答从_outbuffer中删除
                std::cout << "<Getoutbuffer: " << Getoutbuffer() << std::endl;
                continue;
            }
            else if (n == 0)
            {
                break;
            }
            else /* n<0 根据errno来进行判断*/
            {
                if (errno == EAGAIN | errno == EWOULDBLOCK)
                {
                    LOG(LogLevel::INFO) << "底层写缓冲区已经满了";
                    /*此时要对Reactor设置使能关心*/

                    break;
                }
                if (errno == EINTR)
                {
                    LOG(LogLevel::INFO) << "信号中断";
                    return;
                }
                else
                {
                    Excepter();
                    return;
                }
            }
        }
        // 此时要么是底层空间不够要么是已经全部发完
        /*void EnableCtrl(int sockfd, bool read, bool write)*/
        if (!IsOutBufferEmpty())
        {
            _owner->EnableCtrl(_sockfd, true, true);
        }
        else if (!IsOutBufferEmpty())
        {
            _owner->EnableCtrl(_sockfd, true, false);
        }
    }

    virtual void Excepter() override
    {
        LOG(LogLevel::ERROR) << "客户端存在问题，断开连接";
        if (_owner->IsInConnection(_sockfd))
            _owner->DelConnection(_sockfd);
    }
    virtual ~ioservice() override
    {
        ::close(_sockfd);
    }

private:
    func_t _func;
};